package com.atguigu.gmall.pms.service.impl;

import com.atguigu.gmall.common.consts.GmallConsts;
import com.atguigu.gmall.pms.config.RabbitmqConfig;
import com.atguigu.gmall.pms.entity.*;
import com.atguigu.gmall.pms.entity.vo.SkuVO;
import com.atguigu.gmall.pms.entity.vo.SpuAttrValueVO;
import com.atguigu.gmall.pms.entity.vo.SpuVO;
import com.atguigu.gmall.pms.feign.GmallSmsClient;
import com.atguigu.gmall.pms.service.*;
import com.atguigu.gmall.sms.vo.SkuSaleVO;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import io.seata.spring.annotation.GlobalTransactional;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.atguigu.gmall.common.bean.PageResultVo;
import com.atguigu.gmall.common.bean.PageParamVo;

import com.atguigu.gmall.pms.mapper.SpuMapper;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
//import org.springframework.util.StringUtils;


@Service("spuService")
public class SpuServiceImpl extends ServiceImpl<SpuMapper, SpuEntity> implements SpuService {
    /*
        去spring化
        @Resource是java的原生注解
     */
    @Resource
    SpuDescService spuDescService;
    @Resource
    SpuAttrValueService spuAttrValueService;
    @Resource
    SkuService skuService;
    @Resource
    RabbitTemplate rabbitTemplate;

    @Override
    public PageResultVo queryPage(PageParamVo paramVo) {
        IPage<SpuEntity> page = this.page(
                paramVo.getPage(),
                new QueryWrapper<SpuEntity>()
        );

        return new PageResultVo(page);
    }

    @Override
    public PageResultVo listByCondition(Long categoryId, PageParamVo paramVo) {
        LambdaQueryWrapper<SpuEntity> queryWrapper = Wrappers.lambdaQuery(SpuEntity.class);
        /*
            如果categoryId为0 查询所有分类下的spu集合
                    不为0  查询指定分类下的spu集合
            如果paramVo中的key为空  没有过滤条件
                    不为空  模糊查询(匹配spu的id或者 标题)

            select * from spu where category_id = xx and (id like '%xxx%' or name like '%xx%');
         */
        if(categoryId.longValue()!=0){
            queryWrapper.eq(SpuEntity::getCategoryId , categoryId);
        }
        String key = paramVo.getKey();

        if(!StringUtils.isEmpty(key)){
            queryWrapper.and(w->w.like(SpuEntity::getId ,key )
                            .or().like(SpuEntity::getName , key));

        }


        return new PageResultVo(this.page(paramVo.getPage(),queryWrapper));
    }
    @GlobalTransactional //分布式事务起始
    @Transactional
    @Override
    public void bigSave(SpuVO spuVO) {
//        System.out.println(spuVO);
        //1、保存spu
        Long spuId = this.saveSpu(spuVO);
//        int i = 1/0;
        //2、保存spu图片:pms_spu_desc
        //pms_spu_desc没有id列，使用spuid作为主键 和spu的数据一一映射，多个图片地址使用逗号拼接为一个字符串
        spuDescService.saveSpuDesc(spuVO, spuId);
        //saveSpu使用了大保存的事务对象，saveSpuDesc自己新建了一个事务对象
        //3、保存spu 平台属性和值
        spuAttrValueService.saveSpuAttrValues(spuVO, spuId);
        //4、保存sku
        skuService.saveSkus(spuVO, spuId);
        /*
            代码执行到当前行远程访问执行已经结束了，sms的分支事务已经结束
            结束的分支事务数据才会被seata-server TC存到分支事务表中

            当前行 pms的分支事务的业务没有结束，所以数据没有被RM提交到TC中保存
         */

//        int i = 1/0;
        //发送spu新增成功的消息
        RabbitmqConfig.rabbitmqConfig.sendSearchMsg(spuId , 2);
    }



    @Transactional(propagation = Propagation.REQUIRED)
    public Long saveSpu(SpuVO spuVO) {
        this.save(spuVO);//新增时：mp会使用雪花算法生成id设置给spuVO对象 再新增
        return spuVO.getId();
    }

    @Override
    public  List<SpuEntity> queryPublishSpuByPage(PageParamVo paramVo, Integer status) {
        IPage<SpuEntity> page = this.page(
                paramVo.getPage(),
                new LambdaQueryWrapper<SpuEntity>()
                        .eq(SpuEntity::getPublishStatus , status)
        );
        List<SpuEntity> spuEntities = page.getRecords();
        return spuEntities;
    }

}